package com.esun.payment_api.service.impl;

import com.esun.common.api.CommonPage;
import com.esun.common.api.CommonResult;
import com.esun.common.bean.PageRequest;
import com.esun.common.utils.AESUtils;
import com.esun.common.utils.SecurityUtils;
import com.esun.payment_api.domain.*;
import com.esun.payment_api.mapper.*;
import com.esun.payment_api.security.model.ChangePasswordBody;
import com.esun.payment_api.service.LogService;
import com.esun.payment_api.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

@Service
public class UserServiceImpl implements UserService {
    @Resource
    UserMapper userMapper;

    @Resource
    SysRoleMapper sysRoleMapper;

    @Resource
    RUserRoleMapper rUserRoleMapper;

    @Resource
    RRoleMenuMapper rRoleMenuMapper;

    @Resource
    SysMenuMapper sysMenuMapper;

    @Resource
    CompanyMapper companyMapper;

    @Resource
    DepartmentMapper departmentMapper;

    @Resource
    LogService logService;
    final String moduleName = "用户模块";

    /**
     * 强密码规则：
     * 1.至少8个字符
     * 2.至少包含一个小写英文字母
     * 3.至少包含一个大写英文字母
     * 4.至少包含一个数字
     * 5.至少包含一个特殊字符
     */
    //密码长度不少于8位且至少包含大写字母、小写字母、数字和特殊符号中的四种
    public static final String PWD_PATTERN = "^(?![A-Za-z0-9]+$)(?![a-z0-9\\W_]+$)(?![A-Za-z\\W_]+$)(?![A-Z0-9\\W_]+$)[a-zA-Z0-9\\W_]{8,}$";

    public CommonResult getUserList(){
        List<User> userList = userMapper.selectByExample(new UserExample());
        return CommonResult.success(userList, "获取用户列表成功");
     }

    public User addUser(User user) throws Exception{
        HashMap<String, String> checkerMap = new HashMap<>();
        checkerMap.put("loginName", user.getLoginName());
        checkerMap.put("companyId", user.getCoId().toString());
        PageRequest pageRequest = new PageRequest();
        pageRequest.setConditions(checkerMap);
        User checkUser = userMapper.getUserByUsername(pageRequest);
        if(checkUser!=null){
            throw new Exception("该公司已经有同登录名的账号存在");
        }

        user.setIsDeleted("0");
        //给密码加密
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        if(userMapper.insertSelective(user)!=1){
            throw new Exception("添加用户失败");
        } else {
            Map<String, String> map = new HashMap<>();
            map.put("loginName", user.getLoginName());
            map.put("companyId", user.getCoId().toString());
            pageRequest.setConditions(map);
            return userMapper.getUserByUsername(pageRequest);
        }
    }

    public CommonResult editUser(User user){
        try {
            User targetUser = userMapper.selectByPrimaryKey(user.getId());
            if (targetUser==null){
                return CommonResult.failed("无法找到此用户");
            } else {
                //如果是修改密码，将传入的密码加密
                if (user.getPassword()!=null){
                    user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
                    Date date = new Date();
                    user.setPwdSetAt(date);
                }

                if (userMapper.updateByPrimaryKeySelective(user) != 1) {
                    return CommonResult.failed("更新用户失败");
                } else {
                    if(user.getCoId()==null){
                        user.setCoId(targetUser.getCoId());
                    }
                    setUserRole(user);
                    return CommonResult.success(null, "更新用户成功，更新用户id为"+user.getId());
                }
            }
        } catch (Exception e){
            logService.writeErrorLog("更新用户失败,参考原因"+e.getMessage(),moduleName);
            return CommonResult.failed("更新用户失败");
        }
    }

    //修改用户的除密码、角色外的基本信息，防止触发复杂的操作。
    //如果有修改密码或是角色的可能，请用editUser接口。
    public CommonResult editUserBasic(User user){
        try {
            User targetUser = userMapper.selectByPrimaryKey(user.getId());
            if (targetUser==null){
                return CommonResult.failed("无法找到此用户");
            } else {
                //将密码、角色置空（从而更新时不改变已有的），并且删除无关的业务逻辑
                user.setPassword(null);
                user.setRoleStr(null);
                if (userMapper.updateByPrimaryKeySelective(user) != 1) {
                    return CommonResult.failed("更新用户失败");
                } else {
                    return CommonResult.success(null, "更新用户成功");
                }
            }
        } catch (Exception e){
            logService.writeErrorLog("更新用户失败，参考原因"+e.getMessage(),moduleName);
            return CommonResult.failed("更新用户失败");
        }
    }

    @Override
    public CommonResult changePassword(ChangePasswordBody changePasswordBody){
//        System.out.println("旧密码：" + changePasswordBody.getOldPassword());
//        System.out.println("新密码：" + changePasswordBody.getNewPassword());
        String newPwd = "";
        try {
            //新密码解密,恢复实际值
            newPwd = AESUtils.decrypt(changePasswordBody.getNewPassword());
//            System.out.println("新密码解密：" + AESUtils.decrypt(changePasswordBody.getNewPassword()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            User targetUser = userMapper.selectByPrimaryKey(changePasswordBody.getId());
            if (targetUser==null){
                return CommonResult.failed("无法找到此用户");
            } else {
                //解密密码，在前端加密后启用
                changePasswordBody.setOldPassword(AESUtils.decrypt(changePasswordBody.getOldPassword()));
                if(SecurityUtils.matchesPassword(changePasswordBody.getOldPassword(), targetUser.getPassword())){
                    changePasswordBody.setNewPassword(AESUtils.decrypt(changePasswordBody.getNewPassword()));
                    targetUser.setPassword(SecurityUtils.encryptPassword(changePasswordBody.getNewPassword()));
                } else {
                    return CommonResult.failed("旧密码输入错误，更改密码失败");
                }
                Date date = new Date();
                //密码更新时间
                targetUser.setPwdSetAt(date);
                //是否需要更新 0-否，1-是
                targetUser.setIsUpdatePwd("0");

                boolean pwdMatches = newPwd.matches(PWD_PATTERN);
//                System.out.println("是否为强密码：" + pwdMatches);
                if (pwdMatches) {
                    if (userMapper.updateByPrimaryKeySelective(targetUser) != 1) {
                        return CommonResult.failed("更新用户失败");
                    } else {
                        return CommonResult.success(null, "用户密码修改成功，该用户id为"+changePasswordBody.getId());
                    }
                } else {
                    return CommonResult.failed("请检查密码是否符合规范");
                }

            }
        } catch (Exception e){
            logService.writeErrorLog("更新密码失败，参考原因"+e.getMessage(),moduleName);
            return CommonResult.failed("更新密码失败");
        }
    }

    @Override
    public CommonResult changePasswordRaw(ChangePasswordBody changePasswordBody){
        //APEX端传入未加密的密码
        String newPwd = "";
        try {
            User targetUser = userMapper.selectByPrimaryKey(changePasswordBody.getId());
            if (targetUser==null){
                return CommonResult.failed("无法找到此用户");
            } else {
                //不给密码解密
                if(SecurityUtils.matchesPassword(changePasswordBody.getOldPassword(), targetUser.getPassword())){
                    targetUser.setPassword(SecurityUtils.encryptPassword(changePasswordBody.getNewPassword()));
                } else {
                    return CommonResult.failed("旧密码输入错误，更改密码失败");
                }
                newPwd = changePasswordBody.getNewPassword();
                Date date = new Date();
                targetUser.setPwdSetAt(date);
                //是否需要更新 0-否，1-是
                targetUser.setIsUpdatePwd("0");
                boolean pwdMatches = newPwd.matches(PWD_PATTERN);
                if (pwdMatches) {
                    if (userMapper.updateByPrimaryKeySelective(targetUser) != 1) {
                        return CommonResult.failed("更新用户失败");
                    } else {
                        return CommonResult.success(null, "用户密码修改成功，该用户id为"+changePasswordBody.getId());
                    }
                } else {
                    return CommonResult.failed("请检查密码是否符合规范");
                }
            }
        } catch (Exception e){
            logService.writeErrorLog("更新密码失败，参考原因"+e.getMessage(),moduleName);
            return CommonResult.failed("更新密码失败");
        }
    }

    public void setUserRole(User user) throws Exception{
        try{
            //第一步 删除原该User的UserRole对应
            RUserRoleExample rUserRoleExample = new RUserRoleExample();
            RUserRoleExample.Criteria rUserRoleExampleCriteria = rUserRoleExample.createCriteria();
            rUserRoleExampleCriteria.andUserIdEqualTo(user.getId());
            List<RUserRole> rUserRoleList = rUserRoleMapper.selectByExample(rUserRoleExample);
            for(RUserRole rUserRole : rUserRoleList){
                rUserRole.setIsDeleted("1");
                rUserRoleMapper.updateByPrimaryKeySelective(rUserRole);
            }
            //第二步 插入新的User Role对应
            //现在的逻辑是按照roleStr，逗号分割的角色名称来上角色。如果需要按照别的方式再改代码
            if(user.getRoleStr()!=null){
                SysRoleExample sysRoleExample = new SysRoleExample();
                SysRoleExample.Criteria sysRoleExampleCriteria = sysRoleExample.createCriteria();
                sysRoleExampleCriteria.andCoIdEqualTo(user.getCoId());
                List<SysRole> sysRoleList = sysRoleMapper.selectByExample(sysRoleExample);
                Map<String, Short> roleMap = new HashMap<>();
                for(SysRole sysRole : sysRoleList){
                    roleMap.put(sysRole.getRoleName(), sysRole.getId());
                }
                String[] userRoleString = user.getRoleStr().split(",");
                for(String roleString :userRoleString){
                    if(roleMap.containsKey(roleString)){
                        //给用户角色表加入该数据
                        RUserRole rUserRole = new RUserRole();
                        rUserRole.setUserId(user.getId());
                        rUserRole.setRoleId(roleMap.get(roleString));
                        rUserRole.setCoId(user.getCoId());
                        rUserRole.setIsDeleted("0");
                        if(rUserRoleMapper.insertSelective(rUserRole)!=1){
                            throw new Exception("添加用户-角色映射出错");
                        }
                    }
                }
            }
        } catch (Exception e){
            throw e;
        }

    }

    public CommonResult getRoleList(Short companyId){
        SysRoleExample sysRoleExample = new SysRoleExample();
        SysRoleExample.Criteria criteria = sysRoleExample.createCriteria();
        criteria.andCoIdEqualTo(companyId);
        criteria.andIsDeletedEqualTo((short)0);
        try{
            List<SysRole> sysRoleList = sysRoleMapper.selectByExample(sysRoleExample);
            return CommonResult.success(sysRoleList, "单位职务表查询成功");
        } catch (Exception e){
            logService.writeErrorLog("单位职务表查询失败，参考原因"+e.getMessage(),moduleName);
            return CommonResult.failed("单位职务表查询失败");
        }
    }

    public CommonResult getUserList(Short companyId, Short departmentId){
        try {
            UserExample userExample = new UserExample();
            UserExample.Criteria criteria = userExample.createCriteria();
            criteria.andCoIdEqualTo(companyId);
            if(departmentId!=null){
                criteria.andDeptIdEqualTo(departmentId);
            }
            criteria.andIsDeletedEqualTo((short)0);
            userExample.setOrderByClause("id desc");
            List<User> userList = userMapper.selectByExample(userExample);
            for(User user : userList){
                user.setPassword(null);
                user.setPwdAlg(null);
                user.setPwdSalt(null);
            }
            CommonPage<User> commonPage = new CommonPage<>();
            commonPage.setList(userList);
            return CommonResult.success(commonPage, "读取用户列表成功");
        } catch (Exception e){
            logService.writeErrorLog("读取用户列表失败，参考原因" + e.getMessage(),moduleName);
            return CommonResult.failed("读取用户列表失败");
        }
    }

    public CommonResult getCompanyList(){
        try {
            CompanyExample companyExample = new CompanyExample();
            CompanyExample.Criteria criteria = companyExample.createCriteria();
            List<Company> companyList = companyMapper.selectByExample(companyExample);
            return CommonResult.success(companyList, "单位字典表获取成功");
        } catch (Exception e){
            logService.writeErrorLog("单位字典表获取失败，参考原因"+e.getMessage(),moduleName);
            return CommonResult.failed("单位字典表获取失败");
        }
    }

    public CommonResult getDepartmentList(Short companyId){
        try {
            DepartmentExample departmentExample = new DepartmentExample();
            DepartmentExample.Criteria criteria = departmentExample.createCriteria();
            if(companyId!=null){
                criteria.andCoIdEqualTo(companyId);
            }
            criteria.andIsDeletedEqualTo("0");
            List<Department> departmentList = departmentMapper.selectByExample(departmentExample);
            return CommonResult.success(departmentList, "部门字典表获取成功");
        } catch (Exception e){
            logService.writeErrorLog("部门字典表获取失败，参考原因"+e.getMessage(),moduleName);
            return CommonResult.failed("部门字典表获取成功");
        }
    }

    public CommonResult getMenuList(Short userId){
        try {
            //第一步 根据用户id,在User_Role对应表中找到其对应的角色
            RUserRoleExample rUserRoleExample = new RUserRoleExample();
            RUserRoleExample.Criteria rUserRoleCriteria = rUserRoleExample.createCriteria();
            rUserRoleCriteria.andUserIdEqualTo(userId);
            rUserRoleCriteria.andIsDeletedEqualTo("0");
            List<RUserRole> rUserRoleList = rUserRoleMapper.selectByExample(rUserRoleExample);
            List<Short> roleIdList = new ArrayList<>();
            for(RUserRole rUserRole : rUserRoleList){
                if(!roleIdList.contains(rUserRole.getRoleId())){
                    roleIdList.add(rUserRole.getRoleId());
                }
            }
            //第二步 根据用户的角色列表，在role_menu对应表中找到其对应的可访问菜单
            RRoleMenuExample rRoleMenuExample = new RRoleMenuExample();
            RRoleMenuExample.Criteria rRoleMenuCriteria = rRoleMenuExample.createCriteria();
            rRoleMenuCriteria.andIsDeletedEqualTo("0");
            rRoleMenuCriteria.andRoleIdIn(roleIdList);
            //不知道用不用带coId
            List<RRoleMenu> rRoleMenuList = rRoleMenuMapper.selectByExample(rRoleMenuExample);
            List<Short> menuIdList = new ArrayList<>();
            for(RRoleMenu rRoleMenu : rRoleMenuList){
                if(!menuIdList.contains(rRoleMenu.getMenuId())){
                    menuIdList.add(rRoleMenu.getMenuId());
                }
            }
            //第三步 根据角色的权限列表，整理出角色的权限list
            SysMenuExample sysMenuExample = new SysMenuExample();
            SysMenuExample.Criteria sysMenuCriteria = sysMenuExample.createCriteria();
            sysMenuCriteria.andIsDeletedEqualTo("0");
            sysMenuCriteria.andIdIn(menuIdList);
            List<SysMenu> sysMenuList = sysMenuMapper.selectByExample(sysMenuExample);
            return CommonResult.success(sysMenuList, "获取可访问菜单列表成功");
        } catch (Exception e) {
            logService.writeErrorLog("获取可访问菜单列表成功，参考原因"+e.getMessage(),moduleName);
            return CommonResult.failed("获取可访问菜单列表失败");
        }

    }

    @Override
    public UserDept getUserDeptById(Short userId) {
        return userMapper.getUserDeptById(userId);
    }
}
